﻿using ACC.Business;
using ACC.Business.Process;
using ACC.Business.Stn;
using ACC.Data;
using ACC.Data.Line;
using ACC.Interface;
using ACC.PrintTemplate;
using ACC.Util.Common;
using ACC.Util.DB;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Xml;

namespace Script
{
    /// <summary>
    /// 
    /// </summary>
    public class ProcessReworkEx : ProcessRework
    {

        protected override XmlDocument ExecuteUnitCommand(string userid, string linename, string cmdname,
            string unitsn, Hashtable param, out bool result, out string Message)
        {
            result = false;
            Message = "";

            if (cmdname.ToLower() == "rework")
            {
                string reworktype = param.ContainsKey("reworktype") ? param["reworktype"].ToString() : "";
                string username = param.ContainsKey("username") ? param["username"].ToString() : "";
                string partno = param.ContainsKey("partno") ? param["partno"].ToString() : "";
                string parttypeid = param.ContainsKey("parttypeid") ? param["parttypeid"].ToString() : "";
                string reworkcode = "replacecomponent";
                string reworkop = "";
                string idname = param.ContainsKey("id_name") ? param["id_name"].ToString() : "";
                string idvalue = param.ContainsKey("id_value") ? param["id_value"].ToString() : "";
                string idvalue_old = param.ContainsKey("id_value_old") ? param["id_value_old"].ToString() : "";
                string itempartno = param.ContainsKey("itempartno") ? param["itempartno"].ToString() : "";
                string rec_id = param.ContainsKey("rec_id") ? param["rec_id"].ToString() : "";
                if(reworktype == "replacecomponent")
                {
                    return DoReplaceComponent(linename, unitsn, idname, idvalue, idvalue_old, itempartno, rec_id, reworktype, username, reworkcode, reworkop, partno, parttypeid);
                }
            }

            return base.ExecuteUnitCommand(userid, linename, cmdname, unitsn, param, out result, out Message);
        }

        public XmlDocument DoReplaceComponent(string linename, string unitsn, string idname, string idvalue, string idvalue_old, string itempartno, string rec_id, string reworktype, string username, string reworkcode, string reworkop, string partno, string parttypeid)
        {
            XmlDocument xmldoc = new XmlDocument();
            //加入XML的声明段落
            XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            xmldoc.AppendChild(xmlnode);

            //加入一个根元素
            XmlElement rootelem = xmldoc.CreateElement("", "root", "");
            xmldoc.AppendChild(rootelem);

            //加入xmlprop元素，本元素用来放一些 XML 属性
            XmlElement xmlprop = xmldoc.CreateElement("xmlprop");
            rootelem.AppendChild(xmlprop);

            DbConnection conn = DataManager.DBHelper.GetConnection(DBHelper.DEFAULT);
            DbTransaction trans = conn.BeginTransaction();
            xmlprop.SetAttribute("result", "0");
            xmlprop.SetAttribute("message", string.Empty);

            try
            {
                // 生成一个History，得到Rec_ID
                var his = CreateRwkUnitHistory(trans, linename, unitsn, username, reworkcode, partno, parttypeid);

                UInt64 nrec_id;
                UInt64.TryParse(rec_id, out nrec_id);
                if (nrec_id > 0 && his.RecID > 0)
                {
                    // 插入新的UnitID
                    // 修改老的UnitID 状态为UsedInPast
                    UpdateComponentStatus(trans, linename, unitsn, partno, idname, idvalue, idvalue_old, itempartno, his.RecID, nrec_id);

                    // 返回 History 的 Rec_ID
                    xmlprop.SetAttribute("unithist_id", his.RecID.ToString());
                }

                //更新内存,将内存中移除掉，这样要用到时会从数据库中重新加载
                var lineData = LineManager.LineDatas[linename];
                if (lineData != null && lineData.RunningData != null)
                {
                    foreach (var rt in lineData.RunningData.RunningPartNos.Values)
                    {
                        rt.RemoveWIPUnit(unitsn);
                        rt.RemoveWIPUnitID(unitsn);

                        rt.RemoveWIPUnit(idvalue_old);
                        rt.RemoveWIPUnitID(idvalue_old);

                        rt.RemoveWIPUnit(idvalue);
                        rt.RemoveWIPUnitID(idvalue);
                    }
                }
                xmlprop.SetAttribute("result", "1");
                trans.Commit();
            }
            catch (Exception ex)
            {
                trans.Rollback();

                xmlprop.SetAttribute("message", ex.Message);
                logger.Error(ex.Message, ex);
            }
            finally
            {
                if (conn != null && conn.State == ConnectionState.Open)
                {
                    conn.Close();
                }
                conn = null;
            }

            return xmldoc;
        }

        /// <summary>
        /// 生成一个返工记录（ACC_UnitHistory表）
        /// </summary>
        /// <param name="trans"></param>
        /// <param name="linename"></param>
        /// <param name="unitsn"></param>
        /// <param name="username"></param>
        /// <param name="reworkcode"></param>
        /// <param name="partno"></param>
        /// <param name="parttypeid"></param>
        /// <returns></returns>
        public WIPUnitHist CreateRwkUnitHistory(DbTransaction trans, string linename, string unitsn, string username, string reworkcode, string partno, string parttypeid)
        {
            WIPUnitHist his = new WIPUnitHist();
            his.RecID = (uint)ACCSID.GetID(ACCSID.UNIT_HISTORY_RECID);
            his.CTime = DateTime.Now;
            his.StartDT = DateTime.Now;
            his.EndDT = DateTime.Now;
            his.Result = WIPUnitHist.UnitHistoryResult.OK;
            his.ComponentSetID = 0;
            his.SegmentCode = "";
            his.CycleType = WIPUnitHist.UnitHistoryCycleType.Normal;
            his.RunType = 0;
            his.Terminal = "";
            his.ReworkCode = reworkcode;

            string sql = TSQLHelper.GetSql("procesrework_createreworkhistory5");
            var param = new Object[] { 
                        his.RecID.ToString(), his.CTime, partno, unitsn, his.Terminal, 0, linename, "REWORK", "", username, his.CycleType,
                        his.RunType, his.StartDT, his.EndDT, his.ComponentSetID.ToString(), his.ReworkCode, his.Result, "", parttypeid, his.SegmentCode};

            logger.Debug(CommUtils.FormatSQL(sql, param));
            DataManager.DBHelper.Update(trans, sql, param);

            return his;
        }

        /// <summary>
        /// 更新被替换的零件状态，插入新的零件绑定记录， ACC_UnitID表
        /// 如果是替换电芯，将电芯位置信息Copy到新的替换电芯上
        /// </summary>
        /// <param name="trans"></param>
        /// <param name="linename"></param>
        /// <param name="unitsn"></param>
        /// <param name="partno"></param>
        /// <param name="idname"></param>
        /// <param name="idvalue"></param>
        /// <param name="idvalue_old"></param>
        /// <param name="itempartno"></param>
        /// <param name="hist_id"></param>
        /// <param name="rec_id"></param>
        public void UpdateComponentStatus(DbTransaction trans, string linename, string unitsn, string partno, string idname, string idvalue, string idvalue_old, string itempartno, UInt64 hist_id, UInt64 rec_id)
        {
            if (rec_id <= 0) return;

            // 修改旧的电芯状态为UsedInPast
            string sql = TSQLHelper.GetSql("LineLoader_OnChangeComponentStatus");
            Object[] param = new Object[] { DateTime.Now, WIPUnitID.WIPUnitIDStatus.UsedInPast, rec_id.ToString() };
            if (logger.IsDebugEnabled) logger.Debug(CommUtils.FormatSQL(sql, param));
            DataManager.DBHelper.Update(sql, param);
            logger.Debug(CommUtils.FormatSQL(sql, param));

            // 插入新的电芯，状态为InUse (InterFGUsed)
            uint newrec_id = (UInt32)ACCSID.GetID(ACCSID.UNIT_UNITID_RECID);
            sql = TSQLHelper.GetSql("unitdataprocess_saveunitidtodb2");
            param = new Object[] { newrec_id.ToString(), DateTime.Now, linename, unitsn,
                        idname, idvalue, DateTime.Now, WIPUnitID.WIPUnitIDStatus.InterFGUsed, itempartno, "REWORK", "0", hist_id.ToString()};
            DataManager.DBHelper.Update(trans, sql, param);
            logger.Debug(CommUtils.FormatSQL(sql, param));

            if (idname != "电芯") return;

            // 查找电芯的位置（在ACC_UnitID_Tag_Value里）
            sql = TSQLHelper.GetSql("loadprocessfunc_createnewunitid1");
            param = new Object[] { linename, idvalue_old, idname };
            var dt = DataManager.DBHelper.Query(trans, sql, param);
            logger.Debug(CommUtils.FormatSQL(sql, param));
            if (dt != null && dt.Rows.Count > 0)
            {
                // 将位置信息Copy到新的替换的电芯上
                string tagValue = dt.Rows[0]["TAG_VALUE"].ToString();
                sql = TSQLHelper.GetSql("procesrework_dochangeunitidtagvalue2");
                param = new Object[] { tagValue, DateTime.Now, linename, idname, idvalue, "位置" };
                if (DataManager.DBHelper.Update(trans, sql, param) == 0)
                {
                    sql = TSQLHelper.GetSql("procesrework_dochangeunitidtagvalue3");
                    param = new Object[] { DateTime.Now, linename, idname, idvalue, "位置", tagValue };
                    DataManager.DBHelper.Update(trans, sql, param);
                }
                logger.Debug(CommUtils.FormatSQL(sql, param));
            }
        }

        public override void DoReprint(string linename, string unitsn)
        {
            string[] param = unitsn.Split(';');
            if (param.Length > 1)
            {
                unitsn = param[0];
            }
            LineData line = LineManager.GetLineData(linename);
            if (line == null)
            {
                logger.Error(String.Format("DoReprint({0}):Line {1} not start or not exists", unitsn, linename));
                return;
            }
            //用此种方法获得wipunit
            WIPUnit unit = LoadProcessFunc.GetWIPUnit(line.RunningData, unitsn);
            if (unit == null)
            {
                logger.Error(String.Format("DoReprint({0}):Unit not exists", unitsn));
                return;
            }
            if (param.Length > 1)
            {
                unit.UnitSN += ";" + param[1];
            }
            OnReprint(line, unit);
        }
        /// <summary>
        /// 执行重新打印
        /// </summary>
        /// <param name="line"></param>
        /// <param name="unit"></param>
        protected override void OnReprint(LineData line, WIPUnit unit)
        {
            string[] param = unit.UnitSN.Split(';');
            if (param.Length > 1)
            {
                unit.UnitSN = param[0];
                //根据获得产线名称，重新打印不同产线的标签
                switch (param[1])
                {
                    case "二维码":
                        PrintPackLabel(unit.line.Cfg.BomCfg[unit.PartNo], unit);
                        break;
                    case "条形码":
                        PrintCustomerLabel(unit.line.Cfg.BomCfg[unit.PartNo], unit);
                        break;
                }
            }
        }

        /// <summary>
        /// 重新打印PACK二维码
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="bomcofg"></param>
        private void PrintPackLabel(BomCfg bomcfg, WIPUnit unit)
        {
            logger.Debug("Begin Reprint PackLabel");
            try
            {
                string finalLabel = "";
                var content = LabelProcess.GetLabelFileContent(bomcfg, "PackLabel_RP", logger);
                if (content != null)
                {
                    string pono = GetOrderNo("PL02", unit.UnitSN);
                    var attrs = GetOrderAttributes(pono);
                    string BoxModel = attrs["box_model"];

                    string cell = GetCellLotNo(unit); //GetCellLotNo(unit.GetUnitIDByIDName("PACK").IDValue);
                    string customerLabel = GetGBCode(unit); //GetGBCode(unit.GetUnitIDByIDName("PACK").IDValue);
                    string time = unit.CTime.ToString("yyyyMMddhhmmss").Substring(0, 8);
                    //string BoxModel = GetBoxModel("PL02", unit.GetUnitIDByIDName("PACK").IDValue);
                    finalLabel = cell + "/" + unit.PartNo + "/" + customerLabel + "/" + time + "/" + "1";
                    content = content.Replace("[PARTNO,CellCode]", finalLabel);
                    content = content.Replace("[PARTNO,Cell]", cell);
                    content = content.Replace("[PARTNO,boxmodel]", BoxModel);
                    content = content.Replace("[PARTNO,partno]", unit.PartNo);
                    PrinterProcess.SendToPrinter(bomcfg.LineCfg.LineData, "PackLabelPrinter", content, logger);
                }
                else
                {
                    logger.Debug("Reprint PackLabel fail,content is null");
                }
            }
            catch (Exception ex)
            {
                //logger.Debug(string.Format("Exception in reprint process,message:{0}", ex.Message));
                logger.Error(ex.Message, ex);
            }
            logger.Debug("End Reprint PackLabel");
        }

        /// <summary>
        /// 重新打印PACK条形码
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="bomcofg"></param>
        private void PrintCustomerLabel(BomCfg bomcfg, WIPUnit unit)
        {
            logger.Debug("Begin Reprint CustomerLabel Label");
            try
            {
                var content = LabelProcess.GetLabelFileContent(bomcfg, "CustomerLabel_RP", logger);
                if (content != null)
                {
                    string pono = GetOrderNo("PL02", unit.UnitSN);
                    var attrs = GetOrderAttributes(pono);
                    string BoxType = attrs["BOX_TYPE"];

                    string customerLabel = GetGBCode(unit); //GetGBCode(unit.GetUnitIDByIDName("PACK").IDValue);
                    //string BoxType = GetBoxType("PL02", unit.GetUnitIDByIDName("PACK").IDValue);
                    content = content.Replace("[PARTNO,CustomerLabel]", customerLabel);
                    content = content.Replace("[PARTNO,boxtype]", BoxType);
                    PrinterProcess.SendToPrinter(bomcfg.LineCfg.LineData, "CustomerLabelPrinter", content, logger);
                }
                else
                {
                    logger.Debug("Reprint CustomerLabel label fail,content is null");
                }
            }
            catch (Exception ex)
            {
                //logger.Debug(string.Format("Exception in reprint process,message:{0}", ex.Message));
                logger.Error(ex.Message, ex);
            }
            logger.Debug("End Reprint CustomerLabel Label");
        }

        protected override UInt32 CheckReworkCode(string line, string reworkcode, string partno, string unitsn, string reworktype, string reworkop, ref string oldop, out string rwkstn)
        {
            rwkstn = string.Empty;
            return 0;
        }

        #region 获取Pack二维码的信息

        Dictionary<string, string> GetOrderAttributes(string orderno)
        {
            var ret = new Dictionary<string, string>();
            var dt = ACC.Data.DataManager.DBHelper.Query(string.Format("SELECT ATTRIBUTEID,VAL FROM IP_WO_ORDER_ATTRIBUTE_VALUE WHERE ORDERNO = '{0}'", orderno));
            if (dt != null && dt.Rows.Count > 0)
            {
                foreach (DataRow row in dt.Rows)
                {
                    ret.Add(row["ATTRIBUTEID"].ToString().ToUpper(), row["VAL"].ToString());
                }
            }

            return ret;
        }

        string GetOrderNo(string line, string unitSN)
        {
            string sql = string.Format("SELECT b.PONO FROM ACC_WO_WORKORDER_DETAIL a, ACC_WO_WORKORDER_HEADER b WHERE a.WONO = b.WONO AND a.UNITSN = '{0}' AND a.LINE = '{1}' ", unitSN, line);
            var dt = DataManager.DBHelper.Query(sql);
            if (dt != null && dt.Rows.Count > 0)
            {
                return dt.Rows[0]["PONO"].ToString();
            }

            return string.Empty;
        }

        /// <summary>
        /// 根据产线名、pack内部追溯码获取Pack箱体类型
        /// </summary>
        /// <param name="line">产线名</param>
        /// <param name="unitsn">pack内部追溯码</param>
        /// <returns>箱体类型</returns>
        //private string GetBoxType(string line, string unitsn)
        //{
        //    string boxType = "";
        //    try
        //    {
        //        string sql = string.Format("SELECT BOXTYPE FROM ACC_GBSN_UNITSN WHERE LINE='{0}' AND UNITSN = '{1}'", line, unitsn);
        //        DataTable dt = DataManager.DBHelper.Query(sql);
        //        if (dt != null && dt.Rows.Count > 0)
        //        {
        //            boxType = dt.Rows[0]["BOXTYPE"].ToString();
        //        }
        //        else
        //        {
        //            logger.Error("get BoxType failed unitsn" + unitsn);
        //        }

        //    }
        //    catch (Exception ex)
        //    {
        //        logger.Error(ex.Message + ex.StackTrace);
        //    }
        //    return boxType;
        //}

        private string GetGBCode(WIPUnit unit)
        {
            string gbSN = string.Empty;
            if (unit != null)
            {
                var unitID = unit.GetUnitIDByIDName("GBSN");
                gbSN = unitID == null ? string.Empty : unitID.IDValue;

                if (string.IsNullOrEmpty(gbSN)) // 向前兼容
                {
                    string sql = string.Format("SELECT TAG_VALUE FROM ACC_UNITSN_TAG_VALUE WHERE LINE='PL02' AND UNITSN = '{0}'", unit.UnitSN);
                    DataTable dt = DataManager.DBHelper.Query(sql);
                    if (dt != null && dt.Rows.Count > 0)
                    {
                        gbSN = dt.Rows[0]["TAG_VALUE"].ToString();
                    }
                }
            }

            return gbSN;
        }

        /// <summary>
        /// 根据产线名、pack内部追溯码获取Pack箱体型号
        /// </summary>
        /// <param name="line">产线名</param>
        /// <param name="unitsn">pack内部追溯码</param>
        /// <returns>箱体型号</returns>
        //private string GetBoxModel(string line, string unitsn)
        //{
        //    string boxModel = "";
        //    try
        //    {
        //        string sql = string.Format("SELECT BOXMODEL FROM ACC_GBSN_UNITSN WHERE LINE='{0}' AND UNITSN = '{1}'", line, unitsn);
        //        DataTable dt = DataManager.DBHelper.Query(sql);
        //        if (dt != null && dt.Rows.Count > 0)
        //        {
        //            boxModel = dt.Rows[0]["BOXMODEL"].ToString();
        //        }
        //        else
        //        {
        //            logger.Error("get BoxModel failed unitsn" + unitsn);
        //        }

        //    }
        //    catch (Exception ex)
        //    {
        //        logger.Error(ex.Message + ex.StackTrace);
        //    }
        //    return boxModel;
        //}

        /// <summary>
        /// 根据Pack内部码获取电芯批次信息
        /// </summary>
        /// <param name="unitsn">Pack内部码</param>
        /// <returns>电芯批次</returns>
        private string GetCellLotNo(WIPUnit unit)
        {
            string cellLot = "", LotL = "", LotM = "", LotR = "";
            try
            {
                if (unit != null)
                {
                    var unitIDs = unit.GetUnitIDsByIDName("模组");
                    foreach (var v in unitIDs)
                    {
                        if (v.Status != WIPUnitID.WIPUnitIDStatus.InUse) continue;

                        string sql = string.Format("SELECT DISTINCT LOTNO FROM ACC_BATTERY_DATA WHERE BARCODE = '{0}'", v.IDValue);
                        var dt = DataManager.DBHelper.Query(sql);
                        if (dt != null && dt.Rows.Count > 0)
                        {
                            if (v.IDValue.Substring(8, 1).ToUpper() == "A")        // 左
                                LotL = dt.Rows[0]["LOTNO"].ToString();
                            if (v.IDValue.Substring(8, 1).ToUpper() == "B")        // 中
                                LotM = dt.Rows[0]["LOTNO"].ToString();
                            if (v.IDValue.Substring(8, 1).ToUpper() == "C")        // 右
                                LotR = dt.Rows[0]["LOTNO"].ToString();
                        }
                    }
                }

                if (string.IsNullOrEmpty(LotL) || string.IsNullOrEmpty(LotM) || string.IsNullOrEmpty(LotR))
                {
                    logger.Error("get cell lot failed unitsn " + unit == null ? string.Empty : unit.UnitSN);
                    return string.Empty;
                }

                if (LotL == LotM && LotM == LotR)
                {
                    // 如果左中右批次一致、直接返回该批次号
                    cellLot = LotR;
                }
                else
                {
                    // 如果左中右批次不一致、则返回右模组的批次，并且在批次后面加上H
                    cellLot = LotR + "H";
                }

                //string cellLot = "";
                //List<string> lsMZ = new List<string>();
                //string LotL = "", LotM = "", LotR = "";
                // 获取Pack绑定的三个模组码
                //string sql = string.Format("SELECT ID_VALUE FROM [DBO].[ACC_UNITID] WHERE ID_NAME = '模组' AND LINE = 'PL02' AND UNITSN = '{0}'", unitsn);
                //DataTable dt = DataManager.DBHelper.Query(sql);
                //if (dt != null && dt.Rows.Count > 0)
                //{
                //    if (dt.Rows.Count >= 3)
                //    {
                //        sql = "SELECT DISTINCT LOTNO FROM [ACC_BATTERY_DATA] WHERE BARCODE IN ( SELECT ID_VALUE FROM [ACC_UNITID]  WHERE LINE = 'PL02_JT' AND ID_NAME = '电芯' AND UNITSN IN (SELECT ID_VALUE FROM [DBO].[ACC_UNITID] WHERE   LINE = 'PL02_MZ' AND ID_NAME = '模组基体' AND UNITSN = '{0}'))";
                //        foreach (DataRow dr in dt.Rows)
                //        {
                //            string mzcode = dr["ID_VALUE"].ToString();      // 模组条码

                //            // 分别获取三个模组各自对应的电芯批次号
                //            dt = DataManager.DBHelper.Query(string.Format(sql, mzcode));
                //            if (dt != null && dt.Rows.Count > 0)
                //            {
                //                if (mzcode.Substring(8, 1).ToUpper() == "A")        // 左
                //                    LotL = dt.Rows[0]["LOTNO"].ToString();
                //                if (mzcode.Substring(8, 1).ToUpper() == "B")        // 中
                //                    LotM = dt.Rows[0]["LOTNO"].ToString();
                //                if (mzcode.Substring(8, 1).ToUpper() == "C")        // 右
                //                    LotR = dt.Rows[0]["LOTNO"].ToString();
                //            }
                //            else
                //            {
                //                logger.Error("get cell lot failed" + mzcode);
                //            }
                //        }

                //        if (LotL == LotM && LotM == LotR)
                //        {
                //            // 如果左中右批次一致、直接返回该批次号
                //            cellLot = LotR;
                //        }
                //        else
                //        {
                //            // 如果左中右批次不一致、则返回右模组的批次，并且在批次后面加上H
                //            cellLot = LotR + "H";
                //        }
                //    }
                //    else
                //    {
                //        logger.Error("get mz count error" + unitsn);
                //    }
                //}
                //else
                //{
                //    logger.Error("get mz failed unitsn" + unitsn);
                //}
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message, ex);
            }

            return cellLot;
        }

        ///// <summary>
        ///// 根据Pack内部码获取电芯批次信息
        ///// </summary>
        ///// <param name="unitsn">Pack内部码</param>
        ///// <returns>电芯批次</returns>
        //private string GetCellLot(string unitsn)
        //{
        //    string cellLot = "";
        //    try
        //    {
        //        string orderNo = GetOrderNo(unitsn);
        //        if (!string.IsNullOrEmpty(orderNo))
        //        {
        //            string sql = string.Format("SELECT DESCRIPTION FROM IP_WO_ORDER WHERE ORDERNO like'%{0}%' ", orderNo);
        //            DataTable dt = DataManager.DBHelper.Query(sql);
        //            if (dt != null && dt.Rows.Count > 0)
        //            {
        //                foreach (DataRow dr in dt.Rows)
        //                {
        //                    cellLot = dr["DESCRIPTION"].ToString();
        //                    if (!string.IsNullOrEmpty(cellLot))
        //                    {
        //                        cellLot = cellLot.Split(';')[0];
        //                        break;
        //                    }
        //                }
        //            }
        //            else
        //            {
        //                logger.Error("get orderno failed unitsn" + unitsn);
        //            }
        //        }
        //        else
        //        {
        //            logger.Error("not find orderno. unitsn:" + unitsn);
        //        }


        //    }
        //    catch (Exception ex)
        //    {
        //        logger.Error(ex.Message + ex.StackTrace);
        //    }
        //    return cellLot;
        //}

        #endregion

    }
}
